package Log

import (
	"fmt"
	"path/filepath"
	"runtime"
	"time"
)

type Logger struct {
	inc              int
	LogId            string
	Writer           BaseWriter //必须是一个实现了 BaseWriter 接口的实例， 没加 * 取地址是因为接口类型参数不允许取地址，如果想切换writer 只需要实现 BaseWriter
	LogDepth         int        // 调用log方法的方法位置【表示获取调用runtime.Caller前的第几个函数的调用位置】
	FilePath         string     //log文件所在的dir目录，必须以 “/” 结尾
	FileNameFormat   string     //日志文件名的时间格式 最多可以每小时一个文件 【2006-01-02 15:04:05.9999】
	Suffix           string     //日志文件后缀
	RefreshFrequency Frequency  //检查更新日志文件的频率， 只支持每小时一次或每天一次 可选值：[0,1]

}

//======【枚举类型定义】 start ============
type Frequency int //日志文件检查更新的频率
func (f Frequency) String() string {
	options := []string{"Hour", "Day"}
	if options[f] != "" {
		return options[f]
	}
	return options[0]
}

const (
	Hour = iota
	Day
)

//======【枚举类型定义】 end ============

//创建Logger实例
func NewLogger(writer BaseWriter, logDepth int, frequency Frequency, filePath, fileNameFormat, suffix string) (Log *Logger) {
	Log = &Logger{
		Writer:           writer,
		LogDepth:         logDepth,
		RefreshFrequency: frequency,
		FilePath:         filePath,
		FileNameFormat:   fileNameFormat,
		Suffix:           suffix,
	}
	go Log.RefreshWriterFile(true) //定期检查更换Log.Writer.file
	return Log
}

//检查更换Log.Writer.file； isWhile 是否循环检查更换日志文件
func (l *Logger) RefreshWriterFile(isWhile bool) {
	for {
		date := time.Now().Format(l.FileNameFormat)
		fileName := date + l.Suffix
		l.Writer.NewFile(l.FilePath, fileName)

		if isWhile != true {
			fmt.Println("只刷新一次日志")
			break
		}

		currentTime := time.Now()
		var frequency int
		if l.RefreshFrequency == Day {
			frequency = 23
		} else { //l.RefreshFrequency==Hour
			frequency = currentTime.Hour()
		}
		startTime := time.Date(currentTime.Year(), currentTime.Month(), currentTime.Day(), frequency, 59, 59, 0, currentTime.Location())
		nextRefreshTimestamp := startTime.Unix() + 1 //下一次刷新日志文件的时间，第二天开始的时间戳 或 下一个小时开始的时间戳
		nowTimestamp := currentTime.Unix()           //当前时间的时间戳
		sleepTime := time.Duration(nextRefreshTimestamp - nowTimestamp)
		//fmt.Println(sleepTime, nextRefreshTimestamp, nowTimestamp)
		<-time.After(sleepTime * time.Second)
	}
}

//向Writer中写入消息
func (l *Logger) Write(msgType string, vars ...interface{}) {
	pc, file, line, _ := runtime.Caller(l.LogDepth)
	callFileName := filepath.Base(file)      //调用info方法的文件名
	funcName := runtime.FuncForPC(pc).Name() //调用info方法的函数名
	//fmt.Println("call:",file,callFileName,funcName,line)
	newVars := []interface{}{}
	for i, v := range vars {
		if i == 1 {
			newVars = append(newVars, " ") //第一个和第二个中间没有空格，所以插入一个
		}
		newVars = append(newVars, v)
	}
	//l.Writer.Write(fmt.Sprintf("%s %s : file[%s] func[%s] line[%d] %s #ip[%s]\n", msgType, getTime(), callFileName, funcName, line, fmt.Sprint(newVars...), GetLocalIP()))
	l.Writer.Write(fmt.Sprintf("%s %s : file[%s] func[%s] line[%d] %s\n", msgType, getTime(), callFileName, funcName, line, fmt.Sprint(newVars...)))
}

//格式化向Writer中写入消息
func (l *Logger) Writef(msgType, format string, vars ...interface{}) {
	pc, file, line, _ := runtime.Caller(l.LogDepth)
	callFileName := filepath.Base(file)      //调用info方法的文件名
	funcName := runtime.FuncForPC(pc).Name() //调用info方法的函数名
	//fmt.Println("call:",file,callFileName,funcName,line)
	//l.Writer.Write(fmt.Sprintf("%s %s : file[%s] func[%s] line[%d] %s #ip[%s]\n", msgType, getTime(), callFileName, funcName, line, fmt.Sprintf(format, vars...), GetLocalIP()))
	l.Writer.Write(fmt.Sprintf("%s %s : file[%s] func[%s] line[%d] %s\n", msgType, getTime(), callFileName, funcName, line, fmt.Sprintf(format, vars...)))
}

func (l *Logger) Close() {
	l.Writer.Close()
}

func getTime() string {
	return time.Now().Format("2006-01-02 15:04:05")
}

/*func GetLocalIP() string {
	addrs, err := net.InterfaceAddrs()  //！！！ 这段代码太耗时了
	if err != nil {
		return ""
	}

	for _, address := range addrs {
		// 检查ip地址判断是否回环地址
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String()
			}
		}
	}
	return ""
}*/
